/*
 * fifoQueueHelper.c
 *
 *  Created on: Feb 8, 2010
 *      Author: diqiu
 */

#include <stdio.h>

#include "include.h"
#include "DataType.h"

#if DEBUG_PRINT_STAT == 1
// Define variables for statistics.
static int totalPacketReceived = 0;
static int totalPacketDropped = 0;
#endif

/* Enqueue a packet into a packet queue.
 * 	packet:	Packet to be enqueued
 * 	queue:	Pointer to the queue
 */
void enqueue(Packet packet, PacketQueue *packetQueue) {
	#if DEBUG_PRINT_STAT == 1
	// Update number of total packet received from Serial Port
	totalPacketReceived = totalPacketReceived + 1;
	#endif
	
	// Update head and tail accordingly
	if (packetQueue->isEmpty) {
        // Enqueuing to an empty queue should not move head or tail
        packetQueue->isEmpty = 0;
    } else if (packetQueue->tail == (packetQueue->head -1 + PACKETQUEUE_SIZE)%PACKETQUEUE_SIZE) {
		// The queue is full.
		packetQueue->head = (packetQueue->head == 0) ? PACKETQUEUE_SIZE-1 : packetQueue->head-1;
		packetQueue->tail = (packetQueue->tail == 0) ? PACKETQUEUE_SIZE-1 : packetQueue->tail-1;
		#if DEBUG_PRINT_STAT == 1
		// Update number of total packet dropped from Queue
		totalPacketDropped = totalPacketDropped + 1;
		#endif
	} else {
		// The queue is not full.
		packetQueue->head = (packetQueue->head == 0) ? PACKETQUEUE_SIZE-1 : packetQueue->head-1;
	}
	// Enqueue the new packet
	Packet *updatePacket = packetQueue->queue+packetQueue->head;
	updatePacket->emulatedMouse = packet.emulatedMouse;
	updatePacket->xPos = packet.xPos;
	updatePacket->yPos = packet.yPos;
    
    #if DEBUG >= 2
    // Dump entire queue
    int iterator;
    Packet currentPacket;
    iterator = packetQueue->tail;
    while (iterator != packetQueue->head){
        currentPacket = packetQueue->queue[iterator]; 
        fprintf(stderr, "Iterator: %d \tMouse #%d \tX Pos:%d \tY Pos:%d\n", iterator, currentPacket.emulatedMouse, currentPacket.xPos, currentPacket.yPos);
        iterator = ((iterator-1) + PACKETQUEUE_SIZE)%PACKETQUEUE_SIZE; 
    }
    currentPacket = packetQueue->queue[iterator]; 
    fprintf(stderr, "Iterator: %d \tMouse #%d \tX Pos:%d \tY Pos:%d\n", iterator, currentPacket.emulatedMouse, currentPacket.xPos, currentPacket.yPos);
    #endif

	#if DEBUG_PRINT_STAT == 1
    fprintf(stderr, "Total number of packet received from Serial Port = %d \n", totalPacketReceived);
    fprintf(stderr, "Total number of packet dropped from Queue = %d \n", totalPacketDropped);
    #endif
}

/* Dequeue a packet from a packet queue
 * 	packetQueue:	Pointer to the queue
 * Returns the packet dequeued
 */
Packet dequeue(PacketQueue *packetQueue) {
	// Setup the return packet
	Packet packet;
	packet.emulatedMouse = (packetQueue->queue+packetQueue->tail)->emulatedMouse;
	packet.xPos = (packetQueue->queue+packetQueue->tail)->xPos;
	packet.yPos = (packetQueue->queue+packetQueue->tail)->yPos;

    // If current tail is same as head, meaning queue has only 1 element,
    //  the queue is going to be empty after dequeue
    if (packetQueue->head == packetQueue->tail) {
        packetQueue->isEmpty = 1;
    } else {
        // Update tail
        packetQueue->tail = (packetQueue->tail == 0) ? PACKETQUEUE_SIZE-1 : packetQueue->tail-1;
    }

	return packet;
}

/* Is the packet queue empty?
 * 	packetQueue:	Pointer to the queue
 * Returns 1 if queue is empty, 0 otherwise.
 */
int isQueueEmpty(PacketQueue *packetQueue) {
    return packetQueue->isEmpty;
}
